home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i040: Email fax-sending package, Part02/05
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 4beb9ab3 f356640f 2c0d96d7 a288ae7b
-
- Submitted-by: klaus u schallhorn <cnix!klaus>
- Posting-number: Volume 24, Issue 40
- Archive-name: faxpax/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: FaxConfig faxhost/faxfonts/diykit.c faxhost/sendfax.c
- # Wrapped by rsalz@litchi.bbn.com on Wed Mar 13 14:08:01 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 2 (of 5)."'
- if test -f 'FaxConfig' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'FaxConfig'\"
- else
- echo shar: Extracting \"'FaxConfig'\" \(25531 characters\)
- sed "s/^X//" >'FaxConfig' <<'END_OF_FILE'
- X#!/bin/sh
- X#
- X# $Header: FaxConfig, 2.2.91, ks
- X# basically a [very much] stripped down and ripped off version of rn/Configure
- X# where it says:
- X# Yes, you may rip this off to use in other distribution packages.
- X# so I did
- X
- Xn=''
- Xc=''
- Xcontains=''
- X
- Xmodemtypes='1'
- X
- Xcharset='i'
- Xdevice="/dev/not_that_one"
- Xdevlock="LCK..nosuchdevice"
- Xdialstr=""
- Xdialtype='T'
- Xnet='y'
- Xnetwide_fax="NETWIDE_FAX"
- Xfaxhost="faxhost"
- Xfaxadmin=`whoami`
- Xfaxadmin="$faxadmin@"`hostname`
- Xfaxfmode='0644'
- Xfaxlib='/usr/local/lib/faxlib'
- Xfaxspool='/usr/local/spool/fax'
- Xfmtype="sierra"
- Xlocalbin='/usr/local/bin'
- Xloglevel='9'
- Xmanshelf='/usr/share/man'
- Xmaxresend='3'
- Xmaxage='1'
- Xmaxtry='5'
- Xtopspeed='7'
- Xuucplocks='/var/spool/locks'
- X
- X
- Xecho "Beginning of configuration questions for faxpak."
- Xecho " "
- X
- X: some greps do not return status, grrr.
- Xecho "grimblepritz" >grimble
- Xif grep blurfldyick grimble >/dev/null 2>&1 ; then
- X contains=contains
- Xelse
- X if grep grimblepritz grimble >/dev/null 2>&1 ; then
- X contains=grep
- X else
- X contains=contains
- X fi
- Xfi
- X
- X: sanity checks
- XPATH='.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc'
- Xexport PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0; kill $$)
- X
- Xif test ! -t 0; then
- X echo "Type 'sh FaxConfig', not 'sh <FaxConfig'"
- X exit 1
- Xfi
- X
- X: first determine how to suppress newline on echo command
- Xecho "Checking echo to see how to suppress newlines..."
- X(echo "hi there\c" ; echo " ") >.echotmp
- Xif $contains c .echotmp >/dev/null 2>&1 ; then
- X echo "...using -n."
- X n='-n'
- X c=''
- Xelse
- X echo "...using \\\c."
- X n=''
- X c='\c'
- Xfi
- Xecho $n "Type carriage return to continue. Your cursor should be here-->$c"
- Xread ans
- Xrm .echotmp
- X
- X: now set up to do reads with possible shell escape
- X: if this does not work on your machine, 1,$s/. myread/read ans/
- Xcat <<EOSC >myread
- Xans='!'
- Xwhile expr "X\$ans" : "X!" >/dev/null; do
- X read ans
- X case "\$ans" in
- X !)
- X sh
- X echo " "
- X echo $n "Your answer: $c"
- X ;;
- X !*)
- X set \`expr "X\$ans" : "X!\(.*\)\$"\`
- X sh -c "\$*"
- X echo " "
- X echo $n "Your answer: $c"
- X ;;
- X esac
- Xdone
- XEOSC
- X
- X
- Xcat <<EOT
- X
- X# general info
- X##############################################################################
- XThis installation shell script asks you some questions regarding the
- Xsetup of faxpak. Currently there is no support for hardware other than
- XSun Microsystems'. To port this to other machines run this script
- Xanyway, but then have a close look at wiring.c. Wiring.c can be used
- Xas a standalone test program with TESTING defined, and with TEST_DEVICE
- Xdefined to a port you can use for testing [you can reconfig any time],
- Xpreferably without interfering logins.
- X
- XThis script builds a header file faxconfig.h, a soft configuration file
- Xfax,config, fax.1 man pages and, if you're lucky, two faxpak fonts.
- X
- XDefault answers are shown in [brackets]. Hitting carriage return accepts
- Xthe defaults. Once you have faxconfig.h and fax.config you can change
- Xeach file by editing it without re-running this script.
- X
- XEOT
- X
- Xecho $n "[Type carriage return to continue] $c"
- X. myread
- Xecho " "
- X
- X
- Xcat <<EOT
- X
- X##############################################################################
- Xfaxpak can run on networked and standalone machines.
- X
- XIf faxpak is networked, it is assumed that one HOST has the faxmodem[s],
- Xwith all other machines acting as CLIENTS, spooling outgoing fax jobs to
- Xthe faxhost.
- X
- XThe faxhosts' duty is to convert incoming text files into group 3 fax files,
- Xand to do the actual transmission, to log what's going on, to report by
- Xmail [if requested] and to do house keeping chores. This is done by entries
- Xin root's crontab which calls sendfax frequently and faxcleanup once a day.
- X
- XEOT
- X
- Xdflt=$net
- Xecho $n "Do you expect to run faxpak on networked machines? [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- X
- X
- Xif [ $ans = y ]
- Xthen
- X
- X cat <<EOT
- X
- X# network info, don't really need much
- X######################################################################
- X"client" machines find the faxhost by calling gethostbyname(FAXHOST),
- Xwith FAXHOST #defined in faxconfig.h on our sita as "faxhost",
- Xand with "faxhost" aliased in /etc/hosts to mbox. mbox is a 3/60 that
- Xacts as our spooling machine [printing, faxing, mail, news archive etc.].
- X
- XEOT
- X
- X dflt=$faxhost
- X echo "Please enter the \"synonym\" your FAXHOST will be known by -"
- X echo $n "[I guess you could enter the name of a known machine]: [$dflt] $c"
- X . myread
- X echo
- X case $ans in
- X '') ans=$dflt;;
- X esac
- X faxhost=$ans
- Xelse
- X net='n'
- X netwide_fax="nonet"
- Xfi
- X
- X
- Xcat <<EOT
- X
- X# we need someone to blame when things go wrong
- X##############################################################################
- XThe bad news is that things DO go wrong. Therefore we may need
- Xsomeone to interfere by hand, or to lend a hand if a user needs help,
- Xor to give the default answer ["You can't to that"].
- X
- XEOT
- Xdflt=$faxadmin
- Xecho $n "Name a patient person suitable for dealing with fax problems: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xfaxadmin=$ans
- X
- X
- X# what arg do we give chmod()
- X##############################################################################
- Xdflt=$faxfmode
- Xecho $n "Please enter the file access perms to be enforced by faxpak: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xfaxfmode=$ans
- X
- Xcat <<EOT
- X
- X
- X# where to put faxlib and the spool dir
- X##############################################################################
- XTo keep things somewhat organised we need to define a /someplace/faxlib,
- Xand a /somewhere/spooldir for faxpak. I prefer to keep them separate from
- Xdistribution libs and spool dirs. I'd also like to know where you keep you
- Xman pages.
- X
- XEOT
- Xdflt=$faxlib
- Xecho $n "Please enter the path to faxlib: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xfaxlib=$ans
- X
- X
- Xdflt=$faxspool
- Xecho $n "And path to faxspool: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xfaxspool=$ans
- X
- X
- Xdflt=$manshelf
- Xecho $n "And your Manual Shelf: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xmanshelf=$ans
- X
- Xcat <<EOT
- X
- X# find competing uucp locks
- X##############################################################################
- XModem logins, uucp transmissions and faxes all the same time and on
- Xthe same modem tend become somewhat garbled. Tell me where uucp keeps
- Xits lock files, so that sendfax dies away instantly if uucp is active
- X[it knows about logins on a port].
- X
- XEOT
- Xdflt=$uucplocks
- Xecho $n "Where does uucp create its lock files: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xuucplocks=$ans
- X
- X
- Xcat <<EOT
- X
- X# local bin for fax
- X##############################################################################
- XAssuming you don't put local executables into /usr/{bin,ucb}, we need
- Xsort of a /local/bin to put the user interface [called fax] into.
- X
- XEOT
- Xdflt=$localbin
- Xecho $n "Where do you keep local executables: [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xlocalbin=$ans
- X
- X
- Xcat <<EOT
- X
- X# max no of resends within one transmission
- X##############################################################################
- XThe last hard wired bit of info is the number of resends. If a page is
- Xgarbled during transmission, the two hardware gizzmos, that is your
- Xfaxmodem on this side and the fax machine on the other end, can agree
- Xto resend that page. I don't know if fax machines have a built in limit
- Xfor the number of resent pages, I do, however, feel safer if I know
- Xsendfax doesn't spend all night resending a page. Having seen the different
- Xlevels of compliance to the CCITT specs, especially european fax machines',
- XI would doubt, if such a limit is enforced.
- X
- XEOT
- Xdflt=$maxresend
- Xecho $n "How often do you permit the resending of a page within one call [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xmaxresend=$ans
- X
- X
- X# have header info, get details for fax.config
- X##############################################################################
- X
- Xif [ $modemtypes = 2 ]
- Xthen
- X mtypestring="faxmodem type, currently class2 and sierra type modems are supported"
- Xelse
- X mtypestring="faxmodem type, currently only sierra type modems are supported"
- Xfi
- X
- Xcat <<EOT
- X
- X# soft configuration, saved in $faxlib/fax.config"
- X##############################################################################
- XMost of the configuration of faxpak can be changed after compiling faxpak.
- XSoftwired details are stashed into $faxlib/fax.config, allowing for easy
- Xalteration once you have faxpak working. The fax.config file stores:
- X
- X1: the ports to which you have faxmodems connected *)
- X2: literal name of lockfile for each port, in case uucp uses these ports
- X as well as faxpak *)
- X3: $mtypestring
- X4: Tone or Pulse dialling
- X5: Highest speed your faxmodems are capable of [RTFFaxmodemM]
- X6: an optinal string to re-enable dialins on the port after sendfax is done,
- X see /etc/uucp/Dialers, or the modem docs, for examples
- X
- X7: wildcarded dialcodes and times, faxes to these area codes are ok *)
- X
- X8: max no of days a fax is allowed to sit in $faxspool
- X9: max no of attempts to send a fax
- X
- Xlog level, 9 logs everything [huge!], 0 only some relevant info
- X
- XFaxConfig only writes a preliminary file including some comments. Feel
- Xfree to edit it to your liking at any time.
- X
- X*) these are best done with an editor, in fact, I don't even ask for
- X dialcode:time pairs. see the file fax.config when done with this script.
- X [you could also call this load sharing between you and me].
- X
- XEOT
- X
- Xdflt=$device
- Xecho $n "Please enter the first port to be used [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xdevice=$ans
- X
- Xdflt=$devlock
- Xecho "Please enter lockname to block uucp while we're"
- Xecho $n "sending out faxes [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xdevlock=$ans
- X
- Xif [ $modemtypes = 2 ]
- Xthen
- X dflt=$fmtype
- X echo $n "Please enter modem type [$dflt] $c"
- X . myread
- X echo
- X case $ans in
- X '') ans=$dflt;;
- X esac
- X fmtype=$ans
- Xfi
- X
- Xdflt=$dialtype
- Xecho $n "Please enter 'P' if you want pulse dialling [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xdialtype=$ans
- X
- Xdflt=$topspeed
- Xecho "Please enter code for highest baud rate your modem can "
- Xecho $n "fax at - see modem manual [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xtopspeed=$ans
- X
- Xdflt=$dialstring
- Xecho "If you feel brave enough [else leave blank and do later]"
- Xecho $n "String to reenable dialins on ports used by faxmodems [$dflt] $c"
- X. myread
- Xecho
- X
- Xdflt=$maxage
- Xecho $n "How many days is a fax allowed to sit in the queue [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xmaxage=$ans
- X
- Xdflt=$maxage
- Xecho $n "How many attempts do you allow to connect to one phone no [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xmaxtry=$ans
- X
- Xdflt=$loglevel
- Xecho $n "What log level do you want sendfax [wiring for testing] to log at [$dflt] $c"
- X. myread
- Xecho
- Xcase $ans in
- X'') ans=$dflt;;
- Xesac
- Xloglevel=$ans
- X
- X
- X
- Xcat <<EOT
- X
- X# charset info
- X##############################################################################
- XAlthough I planned to support quite a few different character sets [with
- Xthe help of several netters] faxpak currently supports the following few.
- XFor those poor souls whose expression is limited to 7 bits, the decision
- Xmust be based on rand().
- X
- XPlease enter the charset you want faxpak to use:
- X
- X i iso 8859.1
- X p pc de facto [code page 850] standard *)
- X 8 pc code page 861
- X
- X*) Some people felt strongly the ibm pc code page 850 is NOT a de facto
- X standard. IMHO it is insofar as the uk, germany, switzerland and some
- X other mid european countries are concerned, where quite a chunk of
- X "the action" takes place. If you still disagree, don't use faxpak.
- X
- XEOT
- X
- Xdflt=$charset
- Xecho $n "What charset do you want to use [$dflt] $c"
- X. myread
- Xecho
- Xecho copying font definition for diy font kit
- Xcase $ans in
- X'p') cp faxhost/faxfonts/diy_ibmpc.def faxhost/faxfonts/diykit.def;;
- X'8') cp faxhost/faxfonts/diy_codep861.def faxhost/faxfonts/diykit.def;;
- X*) cp faxhost/faxfonts/diy_iso.def faxhost/faxfonts/diykit.def;;
- Xesac
- X
- Xrm -f myread grimble
- X
- X
- X# have fax.config, write faxconfig.h and fax.config
- X###################################################
- X
- Xecho "writing faxconfig.h"
- X
- Xcat >faxconfig.h <<EOT
- X
- X/*
- X fax configuration header [faxconfig.h],
- X shared by faxclient/fax.c, and faxhost/*.c
- X
- X Copyright (C) 1991, klaus schallhorn, klaus@cnix.uucp
- X
- X Permission to use, copy, modify, and distribute this software
- X and its documentation for any purpose and without fee is hereby
- X granted, provided that the above copyright notice appear in
- X all copies and that both that copyright notice and this permission
- X notice appear in supporting documentation.
- X
- X This software is provided "as is" without express or implied warranty.
- X*/
- X
- X#define $netwide_fax
- X
- X
- X /* some common bits 'n pieces */
- X#ifndef TRUE
- X#define TRUE 1
- X#define FALSE 0
- X#define ERROR (-1)
- X#endif
- X
- X#ifndef min
- X#define min(a,b) ((a<b)?a:b)
- X#define max(a,b) ((a>b)?a:b)
- X#endif
- X
- X
- X /* network stuff */
- X#ifdef NETWIDE_FAX
- X#define FAXHOST "$faxhost" /* get host by name */
- X#endif
- X
- X
- X /* application specific stuff */
- X#define FAXADMIN "$faxadmin" /* mail errors if !user */
- X#define FAXFMODE $faxfmode /* for chmod */
- X#define FAXSERVER "spool.fax" /* name of spool pgm */
- X#define FAXLIB "$faxlib" /* needed on faxhost only */
- X#define FAXSPOOL "$faxspool" /* needed on faxhost only */
- X
- X#define UUCPLOCKS "$uucplocks" /* again host only */
- X#define LOCALBIN "$localbin" /* client && host, for fax.c */
- X
- X#define MAX_RESEND $maxresend /* don't resend a page forever */
- X#define FAXLFONT "textfaxl.font" /* lores bitmap font from diykit */
- X#define FAXHFONT "textfaxh.font" /* hires bitmap font from diykit */
- X#define PSFONT "Courier-Bold12" /* ghostscript font */
- X
- X#define MAX_FAX_LINES 2400 /* is a bit generous, so what */
- X
- X#define COARSE 1 /* 204.15 by 97.79 dpi */
- X#define FINE 2 /* 204.15 by 195.58 dpi */
- X#define HP 3
- X
- X#define ASCII 0 /* use hp laser jet compat font to create pbm */
- X#define PBM 1 /* use as is, sort of */
- X /* these aren't done yet, see wiring.c, why */
- X#define DVI 2 /* dvi2ps, NOT YET DONE */
- X#define GHOSTSCRIPT 3 /* ideas [not yet] stolen from mit ai labs */
- X#define HPCL 4 /* hp laser jet compat output */
- X
- X
- X /* fax modem specific bits */
- X#define BETA_FIRMWARE /* applies to wiring.c */
- X#define SIERRA /* type of fax modem */
- X
- X
- X#ifdef NEED_FAXTYPES /* needed in fax.c and spool.fax.c */
- Xstruct ftypes
- X{
- X char *typename;
- X int typeid;
- X} faxtypes[] =
- X{
- X "ascii", ASCII,
- X "pbm", PBM,
- X "dvi", DVI,
- X "postscript", GHOSTSCRIPT,
- X "hpcl" HPCL
- X};
- X#define MAX_FTYPE sizeof(faxtypes)/sizeof(struct ftypes)
- X#endif /* need fax types */
- X
- X
- Xstruct FAX
- X{
- X long spooled;
- X char user[80];
- X#ifdef JOBID
- X char jobid[80];
- X#endif
- X char dname[256];
- X char xname[256];
- X char **phone;
- X int tries,
- X hires,
- X uid,
- X now,
- X mail,
- X pages,
- X type,
- X phone_nos;
- X long tpos,
- X ppos;
- X};
- XEOT
- X
- Xecho "writing fax.config"
- X
- Xcat >fax.config <<EOT
- X# fax.config
- X# Copyright (C) 1991 klaus schallhorn, klaus@cnix.uucp
- X#
- X# Permission to use, copy, modify, and distribute this software
- X# and its documentation for any purpose and without fee is hereby
- X# granted, provided that the above copyright notice appear in
- X# all copies and that both that copyright notice and this permission
- X# notice appear in supporting documentation.
- X#
- X# This software is provided "as is" without express or implied warranty.
- X#
- X#
- X# fax devices
- X# ===========
- X# 2nd column contains the actual device for sendfax
- X# ie /dev/cua1
- X#
- X# 3rd col states lock name to be used so that uucp does not even try
- X# to interfere while we're faxing. Stating the lock name verbatim is
- X# essential since there are differences between HDB uucp and older/other
- X# versions.
- X# NOTE: if you don't share faxmodems with uucp, locknames don't really
- X# matter as long as each port has a distinctive lockname. fred1, fred2
- X# ... fredn would be acceptable.
- X#
- X# 4th col specifies the modem type connected to that port so sendfax knows
- X# how to talk to the hardware.
- X#
- X# 5th col is either T [as in tone dialling] or P [pulse].
- X#
- X# 6th col is highest speed you want to connect at, see your modem manual.
- X#
- X# 7th col is a string sent to the fax modem AFTER we've used it IF you
- X# want to enable incoming calls/getty, for a typical string see
- X# /etc/uucp/Diallers, string has to be "in quotes", absence of a string
- X# implies nothing to send.
- X#
- X# this is what fax.config looks here
- X# 1st 2nd 3rd 4th 5th 6th 7th
- X#device /dev/cua1 LCK..cua1 sierra T 7 "ATE1M0V1X1Q0S2=127S0=4S12=255"
- X#device /dev/cua2 LCK..cua2 sierra T 7 "ATE1M0V1X1Q0S2=127S0=4S12=255"
- Xdevice $device $devlock $fmtype $dialtype $topspeed $dialstr
- X#
- X#
- X# phone bill saver
- X# ================
- X#
- X# I do not want faxes at peak rates, except local ones.
- X#
- X# long distance call phone nos start with a zero PLUS any combination of
- X# digits 1 to 9 [1-9][1-9]*
- X# NOTE: no zeros in 2nd or 3rd digit, except if 2nd digit > 1
- X#
- X# international ones start with 010 cty code PLUS any combination of 1 to 9
- X#
- X# This feature can be raped to make sure faxes to specific fax numbers
- X# are only sent at an acceptable [for the recipient] time, as shown in the
- X# first "hour entry". Hard coded phone nos should come before wild card
- X# entries.
- X#
- X# This sample states that long distance is ok from 6 pm to 6 am,
- X# international ones from 8 pm to 6 am
- X#
- X#hours 0104977777777 9 - 12 # this guy can only be sent to in the morning
- X#hours 01049123456 8 - 10 14 16 - 19
- X#hours 0[1-9][1-9]* 18 - 6 # as in 078 123 6789
- X#hours 0[2-9]* 18 - 6 # as in 030 455 6748
- X#hours 010[1-9]* 20 - 6 # as in 01049 30 345 6789
- X#
- X#
- X# max age of files in spool dir [days], fax is supposed to be fast!
- X# =============================
- X#
- Xmaxage $maxage
- X#
- X#
- X# max number of attempts to connect
- X# =================================
- X#
- Xmaxtry $maxtry
- X#
- X# log level
- X# =========
- X#
- X# 9 = everything
- X# 0 = errors, transmission times
- X# other useful levels are 3 and 5
- X#
- Xloglevel $loglevel
- X#
- X#
- X# end of fax.config
- XEOT
- X
- X# now save fax.1 man pages
- X##########################
- X
- Xecho "writing faxclient/fax.1 man pages"
- X
- Xcat >faxclient/fax.1 <<EOT
- X.TH fax 1 "Feb 4th, 1991"
- X.SH NAME
- Xfax \- send a Group 3 fax via faxmodem.
- X.SH SYNOPSIS
- Xfax phone_no [-a -f -h -l -m -n -r -s] file
- X.SH DESCRIPTION
- XFax accepts ascii input and sends it as a group 3 fax
- Xusing a sierra type faxmodem. The first parameter is either
- Xa phone number, an alias [see aliases] or a distribution list [see lists]
- Xfile name.
- X.sp
- XIf the first parameter contains digits only, it is
- Xassumed to be a phone number.
- X.sp
- XIf your site does enforce permissions, you may have to ask your
- Xadministrator [$faxadmin] for permission to fax.
- X.SH PARAMETERS
- X.TP
- X.B -a'for the attention of...'
- XTo specify a recipient within an organization for internal
- Xrouting. The string must be quoted so it's passed as one
- Xargument to fax. It is then prepended to the outgoing message.
- X.TP
- X.B -f/absolute/font/path/fontfile
- XUse an alternative font. In addition to the default typewriter fonts
- Xin low and high resolution fax knows about
- XHP Laserjet compatible fonts [up to 30 points in height]. These are
- Xscaled to the resolution of the outgoing fax. Used with low resolution
- Xthe output is not pretty.
- X.TP
- X.B -h
- XUse high resolution mode [204 by 195 dots per inch]. This almost doubles
- Xthe transmission time.
- X.TP
- X.B -l
- XUse low resolution mode [204 by 97 dots per inch].
- X.TP
- X.B -m
- XReport by mail as soon as the fax has been sent. Fatal errors or failure
- Xto deliver is reported back irrespectible of the mail flag setting.
- X.TP
- X.B -n
- XSend the fax "now" rather than at cheap rate, where "now" refers
- Xto the next time the fax daemon runs. To bypass the time restrictions [if
- Xany] you may need to have special permission.
- X.TP
- X.B -r'return fax number string'
- XThis string is prepended to the outgoing fax to specify a return
- Xfax number. Currently fax does not support incoming faxes.
- X.TP
- X.B -s
- XSave outgoing faxes in HOME/Fax.Sent/phone.date. Fax saves outgoing faxes in
- Xfiles whose name is a concatenation of recipient and date. If the recipient
- Xis not an alias and not a distribution list, the phone number is
- Xused for the first part of the file name.
- X.PP
- XFile is an ascii file containing a formatted message.
- X.SH DEFAULTS
- XYou can override built in defaults by creating a file ".faxrc" in
- Xyour home directory. This file is consulted before fax reads
- Xcommand line parameters.
- X.sp
- XPermitted default values in .faxrc are those that apply to
- Xall outgoing faxes sent by one user. Command line option override
- Xthese dafaults, however.
- X.TP
- X.B font
- XThe name of a font to be used by fax. The font has to be available
- Xon the machine running the fax daemon. The fontfile
- Xmust be accessible to the fax daemon.
- X.TP
- X.B resolution
- XCan be high or low [see above]. Default: low.
- X.TP
- X.B mail
- XSet to yes for notification by mail. Default: no.
- X.TP
- X.B now
- XSet to yes for sending next time the fax queue is checked
- Xfor outgoing faxes. Default: no.
- X.TP
- X.B retfax
- XA string to be prepended all your outgoing faxes. No default string.
- X.TP
- X.B save
- XIf set, saves files in HOME/Fax.Sent/phone.date. Default: no.
- X.SH ALIASES
- XIf the first parameter to fax contains alphabetic characters, fax first
- Xchecks your HOME directory for a file fax.aliases. This file contains
- Xa list of names, phone numbers, optionally ftao [for the attention of]
- Xstrings to be prepended to each outgoing fax. Anything appearing after a #
- Xsign is treated as a comment.
- X.sp
- XA sample fax.aliases file might look:
- X.sp
- X.nf
- Xfred 12345678 :For the attn of Fred Bloggs # comment
- Xbill 98765
- Xsue 765432389 :The Lady in Pink # another comment
- X.fi
- X.SH LISTS
- XIf an alias is not found in fax.aliases, fax tries to open a distribution
- Xlist with the same name. Distribution lists are similar to alias files.
- XA sample distribution list might look:
- X.sp
- X.nf
- X12345678 :For the attn of Fred Bloggs # comment
- X98765
- X765432389 :The Lady in Pink # another comment
- X.fi
- X.SH INTERACTIVE USE
- XIf fax is not given a file name on the command line, it reads
- Xit's standard input until a line starting with a '.' is encountered,
- Xor until EOF.
- X.sp
- XEntering of a fax can be aborted by hitting ^C. Entering ~v at the beginning of
- Xa line calls the default editor, if specified by the environment variable
- XEDITOR, or /usr/ucb/vi.
- X.sp
- XStarting a line with ~p prints the message entered to far.
- X.SH AUTHOR
- XKlaus Schallhorn
- X.SH COPYRIGHT
- XCopyright (C) 1991 Klaus Schallhorn, klaus@cnix.uucp
- X.sp
- XPermission to use, copy, modify, and distribute this software and its
- Xdocumentation for any purpose and without fee is hereby granted, provided
- Xthat the above copyright notice appear in all copies and that both that
- Xcopyright notice and this permission notice appear in supporting
- Xdocumentation. This software is provided "as is" without express or
- Ximplied warranty.
- XEOT
- X
- Xecho "writing Makefiles"
- X
- Xcat >Makefile <<EOT
- X# Makefile for faxpak
- X#
- X# Copyright (C) 1991 klaus schallhorn, klaus@cnix.uucp
- X#
- XCC = cc
- XCFLAGS = -O2
- XLDFLAGS = -s
- X
- XFAXLIB = $faxlib
- XFAXFMODE = $faxfmode
- XLOCALBIN = $localbin
- XMANSHELF = $manshelf
- X
- XSHELL = /bin/sh
- X
- XSUBS = faxclient faxhost faxhost/faxfonts
- X
- X
- Xall:
- X for i in \$(SUBS) ; do \
- X ( cd \$\$i ; make \$(MFLAGS) 'CC=\$(CC)' 'CFLAGS=\$(CFLAGS)' 'LDFLAGS=\$(LDFLAGS)' all ); \
- X done
- X
- Xinstall:
- X for i in \$(SUBS) ; do \
- X ( cd \$\$i ; make \$(MFLAGS) 'LOCALBIN=\$(LOCALBIN)' 'MANSHELF=\$(MANSHELF)' 'FAXLIB=\$(FAXLIB)' 'FAXFMODE=\$(FAXFMODE)' install ); \
- X done
- X
- Xclean:
- X -rm -f Part?? *.hdr fax.config
- X for i in \$(SUBS) ; do \
- X ( cd \$\$i ; make \$(MFLAGS) clean ); \
- X done
- X
- XEOT
- X
- Xcat >faxclient/Makefile <<EOT
- X# Makefile for faxclient
- X
- Xall: fax
- X
- Xfax: fax.o
- X cc -o fax \$(LDFLAGS) fax.o
- X
- Xfax.o: fax.c
- X cc \$(CFLAGS) -c fax.c
- X
- Xinstall: bininstall maninstall
- X
- Xbininstall: fax
- X cp fax \$(LOCALBIN)
- X
- Xmaninstall: fax.1
- X cp fax.1 \$(MANSHELF)/man1
- X chmod 644 \$(MANSHELF)/man1/fax.1
- Xclean:
- X -rm -f *.o *.a core fax
- X
- XEOT
- X
- Xcat >faxhost/Makefile <<EOT
- X# Makefile for faxhost
- X
- XFAXCLEANUP = faxcleanup.o faxlog.o
- XSENDFAX = sendfax.o wiring.o faxlog.o
- XSPOOLFAX = spool.fax.o faxlog.o
- XTEXTTOPBM = texttopbm.o fntwrite.o
- XFAXHDR = ../faxconfig.h
- X
- XPGMS = faxcleanup sendfax spool.fax texttopbm
- XTEXTFILES = fax.config textfaxl.font textfaxh.font
- X
- Xall: \$(PGMS)
- X
- Xfaxcleanup: \$(FAXHDR) \$(FAXCLEANUP)
- X cc -o faxcleanup \$(LDFLAGS) \$(FAXCLEANUP)
- X
- Xsendfax: \$(FAXHDR) sierracmd.h \$(SENDFAX)
- X cc -o sendfax \$(LDFLAGS) \$(SENDFAX)
- X
- Xspool.fax: \$(FAXHDR) \$(SPOOLFAX)
- X cc -o spool.fax \$(LDFLAGS) \$(SPOOLFAX)
- X
- Xtexttopbm: \$(FAXHDR) \$(TEXTTOPBM)
- X cc -o texttopbm \$(LDFLAGS) \$(TEXTTOPBM)
- X
- Xinstall:
- X cp \$(PGMS) \$(FAXLIB)
- X cp ../fax.config \$(FAXLIB)
- X for i in \$(TEXTFILES) ; do \
- X ( chmod \$(FAXFMODE) \$(FAXLIB)/\$\$i ); \
- X done
- X for i in \$(PGMS) ; do \
- X ( chmod 0500 \$(FAXLIB)/\$\$i ); \
- X done
- X chmod 6711 \$(FAXLIB)/spool.fax
- X chown root.daemon \$(FAXLIB)/*
- X
- Xclean:
- X -rm -f *.o *.a core \$(PGMS)
- X
- XEOT
- X
- Xcat >faxhost/faxfonts/Makefile <<EOT
- X# Makefile for faxhost/faxfonts
- X
- X# path for textfax?.font is hardwired into diykit [in ../../faxconfig.h]
- Xall: diykit lores.data hires.data \
- X $faxlib/textfaxl.font $faxlib/textfaxh.font
- X
- Xdiykit: diykit.o
- X cc -o diykit \$(LDFLAGS) diykit.o
- X
- Xdiykit.o: ../../faxconfig.h diykit.h diykit.c
- X cc \$(CFLAGS) -c diykit.c
- X
- X# path for textfax?.font is hardwired into diykit [in ../../faxconfig.h]
- X$faxlib/textfaxl.font: lores.data
- X ./diykit
- X
- X$faxlib/textfaxh.font: hires.data
- X ./diykit
- X
- Xlores.data: lores.uue
- X uudecode lores.uue && uncompress lores.data.Z
- X
- Xhires.data: hires.uue
- X uudecode hires.uue && uncompress hires.data.Z
- X
- X
- Xinstall:
- X
- Xclean:
- X -rm -f *.o *.a *.data core diykit
- X
- XEOT
- X
- X# end of FaxConfig
- END_OF_FILE
- if test 25531 -ne `wc -c <'FaxConfig'`; then
- echo shar: \"'FaxConfig'\" unpacked with wrong size!
- fi
- # end of 'FaxConfig'
- fi
- if test -f 'faxhost/faxfonts/diykit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'faxhost/faxfonts/diykit.c'\"
- else
- echo shar: Extracting \"'faxhost/faxfonts/diykit.c'\" \(5399 characters\)
- sed "s/^X//" >'faxhost/faxfonts/diykit.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include <malloc.h>
- X#include <ctype.h>
- X#include "diykit.h"
- X
- X#include "../../faxconfig.h"
- X
- Xstatic char *PGM = "diykit";
- Xchar charset[128];
- Xint bm_len;
- Xextern int errno;
- X
- Xstruct FNT_BITMAP /* one for each char */
- X{
- X short *SH;
- X short active;
- X} font[256];
- X
- X
- Xfont_init(name)
- Xchar *name;
- X{
- X FILE *hp;
- X int i;
- X struct FNT_BITMAP *cf;
- X static int fst;
- X char tmp[4];
- X
- X errno = 0;
- X if (!fst)
- X for (i=0; i<256; i++) /* just to be safe */
- X {
- X cf = &font[i];
- X cf->SH = (short *)NULL;
- X cf->active = 0;
- X }
- X else for (i=0; i<256; i++) /* just to be safe */
- X {
- X cf = &font[i];
- X if (cf->SH)
- X free(cf->SH);
- X cf->SH = (short *)NULL;
- X cf->active = 0;
- X }
- X
- X if ((hp = fopen(name, "r")) == NULL)
- X {
- X fprintf(stderr,"%s: can't open %s font, errno %d\n",PGM,name,errno);
- X return(ERROR);
- X }
- X
- X if (fread(tmp, sizeof(char), 3, hp) != 3)
- X {
- X fprintf(stderr,"%s: can't read fontfile %s, errno %d\n",PGM,name,errno);
- X return(ERROR);
- X }
- X if (!strncmp(tmp, "fxL", 3))
- X bm_len = 16;
- X else if (!strncmp(tmp, "fxH", 3))
- X bm_len = 32;
- X else
- X {
- X fprintf(stderr,"%s: %s is not a bitmap font\n",PGM,name);
- X return(ERROR);
- X }
- X
- X if (rd_diykit(hp))
- X return(ERROR);
- X
- X fclose(hp);
- X ++fst;
- X return(0);
- X}
- Xrd_diykit(fp)
- XFILE *fp;
- X{
- X int i, lastc;
- X struct FNT_BITMAP *cf;
- X short cur_char;
- X char curchar[8];
- X
- X for (cur_char=0;;)
- X {
- X lastc = cur_char;
- X /* not all machines are big endian ones */
- X /* diykit therefore stores cur_char as a */
- X /* 4 byte ascii string. It is, however written */
- X /* as a short. */
- X if ((i = fread(curchar, 4, 1, fp)) != 1)
- X {
- X if (cur_char > 0x7e && (!i))
- X break;
- X fprintf(stderr,"%s: read error %d in font\n",PGM,errno);
- X return(ERROR);
- X }
- X curchar[4] = '\0';
- X cur_char = (short)atoi(curchar);
- X if (cur_char <= 0x20 || cur_char > 0xff)
- X {
- X fprintf(stderr,"%s: illegal curchar value %04x after char %3d\n",
- X PGM,cur_char,lastc);
- X return(ERROR);
- X }
- X cf = &font[cur_char];
- X
- X if ((cf->SH = (short *)malloc(bm_len * sizeof(short))) == (short *)NULL)
- X {
- X fprintf(stderr,"%s: not enough memory for bitmap array char %d\n",
- X PGM,cur_char);
- X return(ERROR);
- X }
- X
- X if (fread(cf->SH, sizeof(short), bm_len, fp) != bm_len)
- X {
- X fprintf(stderr,"%s: read error %d for char bitmap %d\n",
- X PGM,errno,cur_char);
- X return(ERROR);
- X }
- X cf->active = TRUE;
- X }
- X return(0);
- X}
- Xwritekit(hp,kit)
- XFILE *hp, *kit;
- X{
- X struct FNT_BITMAP *cf;
- X short cur_char, i, pos;
- X char tmp[4];
- X
- X if (bm_len == 16)
- X strcpy(tmp, "fxL");
- X else strcpy(tmp, "fxH");
- X
- X if (fwrite(tmp, sizeof(char), 3, hp) != 3)
- X {
- X fprintf(stderr,"%s: write error %d on fontfile\n",PGM,errno);
- X return(ERROR);
- X }
- X
- X for (cur_char=33; cur_char<128; cur_char++)
- X {
- X cf = &font[cur_char];
- X if (cf->active)
- X {
- X if (fwrite(&cur_char, sizeof(short), 1, hp) != 1)
- X {
- X fprintf(stderr,"%s: write error %d on font\n",
- X PGM,errno);
- X return(ERROR);
- X }
- X if (fwrite(cf->SH, sizeof(short), bm_len, hp) != bm_len)
- X {
- X fprintf(stderr,"%s: write error %d on font\n",
- X PGM,errno);
- X return(ERROR);
- X }
- X }
- X }
- X
- X while ((cur_char = getnext_char(&pos,kit)) != EOF)
- X {
- X cf = &font[cur_char];
- X if (cf->active)
- X {
- X if (fwrite(&pos, sizeof(short), 1, hp) != 1)
- X {
- X fprintf(stderr,"%s: write error %d on font\n",
- X PGM,errno);
- X return(ERROR);
- X }
- X if (fwrite(cf->SH, sizeof(short), bm_len, hp) != bm_len)
- X {
- X fprintf(stderr,"%s: write error %d on font\n",
- X PGM,errno);
- X return(ERROR);
- X }
- X }
- X }
- X return(0);
- X}
- Xgetnext_char(pos,fp)
- Xshort *pos;
- XFILE *fp;
- X{
- X char buf[128], charname[40];
- X int found, Pos;
- X static int line;
- X
- X for (;;)
- X {
- X if (fgets(buf, 126, fp) == NULL)
- X return(EOF);
- X ++line;
- X if (buf[0] != '#')
- X {
- X if (sscanf(buf,"%d %s",&Pos,charname) < 2)
- X {
- X fprintf(stderr,"%s: def file looks wrong to me at line %d\n",PGM,line);
- X return(EOF);
- X }
- X *pos = Pos;
- X if ((found = find_def(charname)) == EOF)
- X {
- X fprintf(stderr,"%s: unknown char def {%s} at at line %d\n",
- X PGM,charname,line);
- X return(EOF);
- X }
- X return(found);
- X }
- X }
- X}
- Xfind_def(s)
- Xchar *s;
- X{
- X int mid, cmp, hi,lo;
- X
- X lo=0;
- X hi = MAX_DEF-1;
- X for (; lo<=hi;)
- X {
- X mid = (lo+hi)/2;
- X if ((cmp = strcmp(s, diy[mid].charname)) < 0)
- X hi = mid-1;
- X else if (cmp > 0)
- X lo = mid+1;
- X else return(diy[mid].chardef);
- X }
- X return(EOF);;
- X}
- Xmain()
- X{
- X FILE *out, *kitfp;
- X char destname[256];
- X
- X errno = 0;
- X if ((kitfp = fopen("diykit.def", "r")) == NULL)
- X {
- X fprintf(stderr,"%s: can't open diykit.def, errno %d\n",errno);
- X exit(1);
- X }
- X
- X if (fgets(charset, 126, kitfp) == NULL)
- X {
- X fprintf(stderr,"%s: can't read charset info on 1st line, errno %d\n",
- X PGM,errno);
- X exit(1);
- X }
- X if (font_init("lores.data"))
- X exit(1);
- X
- X sprintf(destname, "%s/%s", FAXLIB, FAXLFONT);
- X if ((out = fopen(destname, "w")) == NULL)
- X {
- X fprintf(stderr,"%s: can't create %s, errno %d\n",
- X PGM,destname,errno);
- X exit(1);
- X }
- X writekit(out,kitfp);
- X fclose(out);
- X chmod(destname, 0644);
- X
- X errno = 0;
- X rewind(kitfp);
- X if (fgets(charset, 126, kitfp) == NULL)
- X {
- X fprintf(stderr,"%s: can't read charset info on 1st line, errno %d\n",
- X PGM,errno);
- X exit(1);
- X }
- X if (font_init("hires.data"))
- X exit(1);
- X
- X sprintf(destname, "%s/%s", FAXLIB, FAXHFONT);
- X if ((out = fopen(destname, "w")) == NULL)
- X {
- X fprintf(stderr,"%s: can't create %s, errno %d\n",
- X PGM,destname,errno);
- X exit(1);
- X }
- X writekit(out,kitfp);
- X fclose(out);
- X fclose(kitfp);
- X chmod(destname, 0644);
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 5399 -ne `wc -c <'faxhost/faxfonts/diykit.c'`; then
- echo shar: \"'faxhost/faxfonts/diykit.c'\" unpacked with wrong size!
- fi
- # end of 'faxhost/faxfonts/diykit.c'
- fi
- if test -f 'faxhost/sendfax.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'faxhost/sendfax.c'\"
- else
- echo shar: Extracting \"'faxhost/sendfax.c'\" \(20157 characters\)
- sed "s/^X//" >'faxhost/sendfax.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include <malloc.h>
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <time.h>
- X#include <sys/types.h>
- X#include <dirent.h>
- X#include <unistd.h>
- X
- X#include "../faxconfig.h"
- X
- X/*
- X sendfax.c
- X
- X called frequently by cron,
- X inspect spool area for jobs to do - and get on with it
- X the actual squirting of data through the serial ports
- X is done in wiring.c
- X this file is concerned mainly with reading config info,
- X collecting and parsing all available x.files and
- X passing them on to forked copies of sendfax to share
- X the load
- X
- X if you have only one faxmodem, all work is done in house
- X without forking off slave clones
- X
- X first released version 0.99 [desperado version]
- X cleaned up Jan 22nd '91,
- X Copyright (C) 1991, klaus schallhorn, klaus@cnix.uucp
- X
- X Permission to use, copy, modify, and distribute this software
- X and its documentation for any purpose and without fee is hereby
- X granted, provided that the above copyright notice appear in
- X all copies and that both that copyright notice and this permission
- X notice appear in supporting documentation.
- X
- X This software is provided "as is" without express or implied warranty.
- X*/
- X
- X#define COME_BACK 0
- X#define GO_AWAY 1
- X
- X#define ALLOWED 1 /* individual permissions, same as cron/at */
- X#define DENIED 2 /* files: fax.allow, fax.deny */
- X#define ROOT 3
- X#define ALL 4
- X
- Xchar faxrun[256], /* make a note that's sendfax is running */
- X tmp[1024],
- X io[1024];
- X
- X
- Xchar **faxjobs; /* list of x.files, jobs to do */
- Xchar **Denied, **Allowed; /* fax permissions, same setup as cron */
- Xchar **CanNow; /* in case the boss wants to override hours */
- X
- Xstatic int pid, /* zip 'em all out to zero */
- X max_age, /* days a fax may hover in spool dir */
- X max_tries, /* max no of attempts to tx a fax [job] */
- X faxperms, /* checking fax.allow && fax.deny */
- X a_cnt, d_cnt, /* number of allowed/denied users */
- X cn_cnt, /* no of unrestricted users */
- X dev_cnt, /* number of devices faxable */
- X todo; /* no of fax jobs in queue */
- X
- Xint blah; /* chattynes for logging */
- X
- Xstruct Hours /* restrict certain area/country codes to cheap hours, */
- X{ /* or local faxes only between midday and noon */
- X char *dialcode;
- X char hours[24];
- X} *hour_ptr;
- Xstatic int h_entries;
- X
- X
- Xstruct config_funcs /* to read fax.config in any order */
- X{
- X int (*funcptr)(); /* function address */
- X char *funcname; /* name used in config file */
- X};
- X
- Xint device(), incoming(), hours(), maxage(), maxtry(), loglevel();
- Xchar **Devices, /* array of device names in /dev */
- X **Devlocks, /* array of lock file names */
- X **Faxtypes, /* array of fax modem types */
- X **Wakeup, /* array of strings to revive modems */
- X *Dialtyp, /* array of T's or P's [tone/pulse] */
- X *Topspeed; /* array of one byte speed indicators */
- X
- Xstruct config_funcs config_table[] =
- X{
- X/* address funcname */
- X { device, "device" },
- X { incoming, "incoming" },
- X { hours, "hours" },
- X { maxage, "maxage" },
- X { maxtry, "maxtry" },
- X { loglevel, "loglevel" }
- X};
- X#define MAX_CONFIG sizeof(config_table)/sizeof(struct config_funcs)
- X
- Xstruct FAX fax;
- X
- Xextern int errno;
- XFILE *popen();
- X
- X
- Xmain(ac,av)
- Xint ac;
- Xchar *av[];
- X{
- X char *PGM;
- X
- X errno = blah = 0;
- X hour_ptr = NULL;
- X Topspeed = Dialtyp = NULL;
- X Allowed = Denied = CanNow = NULL;
- X Devices = Devlocks = Faxtypes = Wakeup = NULL;
- X
- X pid = getpid();
- X
- X if ((PGM = strrchr(av[0], '/')) != NULL)
- X PGM++;
- X else PGM = av[0];
- X
- X#ifndef TESTING
- X if (fork()) /* errs, parent, or unwanted relatives */
- X exit(0);
- X if (setpgrp(0,0))
- X {
- X fax_log(ERROR, "sendfax: can't create new prgp\n");
- X exit(1);
- X }
- X#endif
- X
- X if (chdir(FAXSPOOL)) /* quick one, job done */
- X {
- X fax_log(ERROR,"sendfax: can't cd to FAXSPOOL\n");
- X exit(1);
- X }
- X if (read_config())
- X exit(1);
- X
- X if (!strcmp(PGM, "rcvfax"))
- X exit(0); /*rcvfax(); when done */
- X else /* sendfax */
- X { /* see if sendfax is active, if so, go away */
- X sprintf(faxrun, "%s/SEND.FAX.RUN",FAXLIB);
- X if (mklock(faxrun, FALSE, FALSE) < 0)
- X {
- X fax_log(5, "sendfax: busy\n");
- X exit(0); /* last cron job of sendfax still busy */
- X }
- X if ((todo = chk_queue()) > 0)
- X {
- X if (!blah)
- X fax_log(0, "sendfax: STARTUP, %d device%c, %d jobs pending\n",
- X dev_cnt,(dev_cnt>1)?'s':' ',todo);
- X else fax_log(9, "sendfax: %d jobs pending\n",todo);
- X runqueue();
- X }
- X fax_log(5, "sendfax: done\n");
- X unlink(faxrun);
- X }
- X exit(0);
- X}
- X
- Xrunqueue()
- X{
- X int i, j, k, brk, in_use, slot, *kid_pids;
- X FILE *X;
- X
- X fax.phone = NULL;
- X
- X if (dev_cnt > 1) /* do this only if more than 1 faxmodem */
- X {
- X if ((kid_pids = (int *)malloc(dev_cnt * sizeof(int))) == NULL)
- X {
- X fax_log(ERROR,"sendfax: can't allocate memory\n");
- X return;
- X }
- X for (i=0; i<dev_cnt; i++)
- X kid_pids[i] = 0;
- X }
- X
- X fax.phone_nos = 0;
- X for (i=in_use=slot=0; i<todo; i++)
- X {
- X fax.tries = fax.uid = fax.now =
- X fax.mail = fax.pages = 0;
- X fax.user[0] = fax.dname[0] = '\0';
- X#ifdef JOBID
- X fax.jobid[0] = '\0';
- X#endif
- X fax.tpos = fax.ppos = fax.spooled = 0L;
- X
- X if ((X = fopen(faxjobs[i], "r+")) == NULL)
- X {
- X fax_log(ERROR,"sendfax: can't open %s\n",faxjobs[i]);
- X return;
- X }
- X
- X if (read_job(X, faxjobs[i]))
- X {
- X fax_log(ERROR,"sendfax: can't read %s\n",faxjobs[i]);
- X return;
- X }
- X fax_log(5, "sendfax: %s, %d fax%s, attempt %d, user %s%s\n",
- X faxjobs[i], fax.phone_nos, (fax.phone_nos>1)?"es":"",
- X fax.tries, fax.user,
- X (fax.tries < max_tries)?"":", CANNOT RETRY");
- X
- X if (fax.tries >= max_tries)
- X {
- X fclose(X);
- X continue;
- X }
- X
- X if (chk_perms())
- X {
- X fclose(X);
- X fax_log(ERROR,"sendfax: user %s not permitted to use fax, mailed user, unlinked files\n",fax.user);
- X rmjob(faxjobs[i],fax.dname,fax.pages);
- X sprintf(tmp,"echo 'you have no permission to fax [fax admin: %s]' | mail %s",FAXADMIN,fax.user);
- X system(tmp);
- X continue;
- X }
- X
- X/*
- X can no longer avoid the issue.
- X if we have just 1 faxmodem, squirt one job now,
- X if we're sharing the load between several devices, find
- X an unused one and fork a copy to do the sending. If no
- X faxmodems avail, wait for one to pop up.
- X
- X All this assumes uucp is not interfering, this is checked
- X in "wiring.c", where we just die away [or return in case
- X of just 1 device] if port cannot be opened
- X*/
- X if (dev_cnt == 1)
- X {
- X sendfax(X, slot, COME_BACK);
- X continue;
- X }
- X
- X for (k=0; k<dev_cnt; k++)
- X if (!kid_pids[k])
- X {
- X slot = k;
- X break;
- X }
- X
- X if ((j = fork()) == ERROR)
- X {
- X fax_log(ERROR,"sendfax: can't fork, giving up\n");
- X return;
- X }
- X else if (!j) /* child */
- X sendfax(X, slot, GO_AWAY);
- X
- X fclose(X); /* still open in child for read/write */
- X kid_pids[slot] = j; /* associate kid's pid with dev */
- X
- X if (++in_use < dev_cnt)
- X continue;
- X
- X for (brk=0; !brk;)
- X {
- X j = wait((int *)NULL); /* don't wanna know x status */
- X for (k=0; k<dev_cnt; k++)
- X if (j == kid_pids[k])
- X { /* make device recycleable */
- X kid_pids[k] = 0;
- X --in_use;
- X brk = TRUE; /* have an unused device */
- X break; /* brk top loop to go on */
- X }
- X }
- X }
- X}
- X
- Xchk_queue()
- X{
- X DIR *dirp;
- X struct dirent *dp;
- X int alloced, entries, i;
- X
- X if ((dirp = opendir(FAXSPOOL)) == NULL)
- X return(fax_log(ERROR,"sendfax: can't open directory %s\n",FAXSPOOL));
- X
- X if ((faxjobs = (char **)malloc(8*sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X alloced = 8;
- X entries = 0;
- X
- X for (;;)
- X {
- X if (entries == alloced)
- X {
- X if ((faxjobs = (char **)realloc(faxjobs,
- X (alloced += 8) * sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X
- X if ((dp = readdir(dirp)) == NULL)
- X break;
- X if (strncmp(dp->d_name, "x.f", 3))
- X continue;
- X
- X if ((faxjobs[entries] = malloc(1+strlen(dp->d_name))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(faxjobs[entries++], dp->d_name);
- X }
- X closedir(dirp);
- X i = entries;
- X while (i < alloced)
- X faxjobs[i++] = NULL;
- X return(entries);
- X}
- Xread_config()
- X{
- X FILE *cfg;
- X char a[256];
- X int i;
- X
- X sprintf(a, "%s/fax.config", FAXLIB);
- X if ((cfg = fopen(a, "r")) == NULL)
- X {
- X fax_log(ERROR,"sendfax: can't open %s/fax.config\n",FAXLIB);
- X return(ERROR);
- X }
- X
- X while (fgets(io, 254, cfg) != NULL)
- X {
- X if (io[0] == '#' || (sscanf(io, "%s",a) < 1))
- X continue;
- X for (i=0; i<MAX_CONFIG; i++)
- X if (!strcmp(a,config_table[i].funcname))
- X {
- X if ((*config_table[i].funcptr)
- X (&io[fstbyte(io,strlen(a))]))
- X {
- X fax_log(ERROR,
- X "strange device spec [%s]\n",io);
- X return(ERROR);
- X }
- X break;
- X }
- X if (i == MAX_CONFIG)
- X fax_log(ERROR,"sendfax: unknown function in config: %s\n",a);
- X }
- X fclose(cfg);
- X if (blah >= 5) /* alternative STARTUP log is in main with blah == 0 */
- X fax_log(5, "sendfax: STARTUP, %d device%c\n",dev_cnt,(dev_cnt>1)?'s':' ');
- X if (get_perms())
- X return(ERROR);
- X return(0);
- X}
- Xfstbyte(s,skip) /* find fst usable item in a config line like: */
- Xchar *s; /* device /dev/copperwire */
- Xint skip;
- X{
- X s += skip;
- X while (*s && isspace(*s))
- X {
- X ++skip;
- X ++s;
- X }
- X return(skip);
- X}
- Xnxtint(s)
- Xchar *s;
- X{
- X char *o;
- X
- X o = s;
- X while (*s && (isdigit(*s) || *s == '-'))
- X ++s;
- X while (*s && isspace(*s))
- X ++s;
- X return((int)(s - o));
- X}
- Xdevice(s)
- Xchar *s;
- X{
- X static int d_alloced;
- X char dev[80], devlck[80], faxtyp[80], dial, speed, *sptr, *eptr;
- X
- X if (sscanf(s,"%s %s %s %c %c",dev,devlck,faxtyp,&dial,&speed) < 5)
- X return(ERROR);
- X
- X if (!d_alloced)
- X {
- X if (((Devices = (char **)malloc(4*sizeof(char *))) == NULL)
- X || ((Devlocks = (char **)malloc(4*sizeof(char *))) == NULL)
- X || ((Faxtypes = (char **)malloc(4*sizeof(char *))) == NULL)
- X || ((Wakeup = (char **)malloc(4*sizeof(char *))) == NULL)
- X || ((Dialtyp = (char *)malloc(4)) == NULL)
- X || ((Topspeed = (char *)malloc(4)) == NULL))
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X d_alloced = 4;
- X }
- X else if (d_alloced == dev_cnt)
- X {
- X d_alloced += 4;
- X if (((Devices = (char **)realloc(Devices,
- X d_alloced * sizeof(char *))) == NULL)
- X || ((Devlocks = (char **)realloc(Devlocks,
- X d_alloced * sizeof(char *))) == NULL)
- X || ((Faxtypes = (char **)realloc(Faxtypes,
- X d_alloced * sizeof(char *))) == NULL)
- X || ((Wakeup = (char **)realloc(Wakeup,
- X d_alloced * sizeof(char *))) == NULL)
- X || ((Dialtyp = (char *)realloc(Dialtyp,
- X d_alloced)) == NULL)
- X || ((Topspeed = (char *)realloc(Topspeed,
- X d_alloced)) == NULL))
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X if (((Devices[dev_cnt] = malloc(1+strlen(dev))) == NULL)
- X || ((Devlocks[dev_cnt] = malloc(1+strlen(devlck))) == NULL)
- X || ((Faxtypes[dev_cnt] = malloc(1+strlen(faxtyp))) == NULL))
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(Devices[dev_cnt], dev);
- X strcpy(Devlocks[dev_cnt], devlck);
- X strcpy(Faxtypes[dev_cnt], faxtyp);
- X Dialtyp[dev_cnt] = dial;
- X Topspeed[dev_cnt] = speed;
- X
- X if (((sptr = strchr(s, '"')) != NULL)
- X && ((eptr = strrchr(s, '"')) != NULL)
- X && (eptr > sptr))
- X {
- X *eptr = '\0';
- X ++sptr;
- X if ((Wakeup[dev_cnt] = malloc(1+(int)(eptr-sptr))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(Wakeup[dev_cnt], sptr);
- X }
- X else Wakeup[dev_cnt] = NULL;
- X
- X ++dev_cnt;
- X return(0);
- X}
- Xincoming(s)
- Xchar *s;
- X{
- X/* haven't had time to do this
- X if (sscanf(s,"%s",Incoming) < 1)
- X*/
- X return(ERROR);
- X}
- Xmaxtry(s)
- Xchar *s;
- X{
- X if (sscanf(s,"%d",&max_tries) < 1)
- X return(ERROR);
- X return(0);
- X}
- Xloglevel(s)
- Xchar *s;
- X{
- X if (sscanf(s,"%d",&blah) < 1)
- X return(ERROR);
- X return(0);
- X}
- Xmaxage(s)
- Xchar *s;
- X{
- X if (sscanf(s,"%d",&max_age) < 1)
- X return(ERROR);
- X return(0);
- X}
- Xhours(s)
- Xchar *s;
- X{
- X static int h_alloced;
- X int i, lasth;
- X char *p;
- X
- X if (sscanf(s,"%s",tmp) < 1) /* expect dial code */
- X return(ERROR);
- X i = strlen(tmp);
- X s += fstbyte(s, i); /* skip him */
- X
- X if (!h_entries)
- X {
- X if ((hour_ptr = (struct Hours *)malloc(
- X (h_alloced += 8) * sizeof(struct Hours))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X else if (h_alloced == h_entries)
- X {
- X if ((hour_ptr = (struct Hours *)realloc(hour_ptr,
- X (h_alloced += 8) * sizeof(struct Hours))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X if ((hour_ptr[h_entries].dialcode = malloc(1+i)) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(hour_ptr[h_entries].dialcode, tmp);
- X
- X p = hour_ptr[h_entries].hours;
- X for (i=0; i<24; i++)
- X *p++ = '\0';
- X
- X lasth = -1;
- X p = hour_ptr[h_entries].hours;
- X
- X while (*s && *s != '#')
- X {
- X if (isdigit(*s))
- X {
- X if ((i = atoi(s)) < 0 || i > 23)
- X return(ERROR);
- X p[i] = '\1';
- X if (lasth > -1)
- X {
- X if (lasth < i)
- X {
- X while (lasth < i)
- X p[lasth++] = '\1';
- X }
- X else
- X {
- X while (lasth < 24)
- X p[lasth++] = '\1';
- X lasth = 0;
- X while (lasth < i)
- X p[lasth++] = '\1';
- X }
- X lasth = -1;
- X }
- X s += nxtint(s);
- X }
- X else if (*s == '-')
- X {
- X lasth = i;
- X s += nxtint(s);
- X }
- X }
- X ++h_entries;
- X return(0);
- X}
- X#define MATCHCMASK 0377
- X#define MATCHQUOTE 0200
- X#define MATCHQMASK (MATCHCMASK&~MATCHQUOTE)
- X#define MATCHNOT '^'
- X
- Xstatic char *cclass();
- X
- Xmatch(s, p)
- Xchar *s, *p;
- X{
- X int sc, pc;
- X
- X while ((pc = *p++ & MATCHCMASK) != '\0')
- X {
- X sc = *s++ & MATCHQMASK;
- X switch (pc)
- X {
- X case '[':
- X if ((p = cclass(p, sc)) == NULL)
- X return(0);
- X break;
- X case '?':
- X if (sc == 0)
- X return(0);
- X break;
- X case '*':
- X s--;
- X do
- X {
- X if (*p == '\0' || match(s, p))
- X return(1);
- X } while (*s++ != '\0');
- X return(0);
- X default:
- X if (sc != (pc & ~MATCHQUOTE))
- X return(0);
- X }
- X }
- X return(*s == 0);
- X}
- X
- Xstatic char *cclass(p, sub)
- Xchar *p;
- Xint sub;
- X{
- X int c, d, not, found;
- X
- X if ((not = *p == MATCHNOT) != 0)
- X p++;
- X found = not;
- X
- X do
- X {
- X if (*p == '\0')
- X return(NULL);
- X c = *p & MATCHCMASK;
- X if (p[1] == '-' && p[2] != ']')
- X {
- X d = p[2] & MATCHCMASK;
- X p++;
- X }
- X else d = c;
- X
- X if (c == sub || c <= sub && sub <= d)
- X found = !not;
- X } while (*++p != ']');
- X
- X return(found ? (p+1) : NULL);
- X}
- Xget_perms()
- X{
- X FILE *fp;
- X int a_alloced, d_alloced, len;
- X
- X a_alloced = d_alloced = 0;
- X sprintf(tmp, "%s/fax.allow", FAXLIB);
- X if ((fp = fopen(tmp, "r")) != NULL)
- X {
- X if ((Allowed = (char **)malloc(8*sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X a_alloced = 8;
- X
- X for (;;)
- X {
- X if (a_cnt == a_alloced)
- X {
- X if ((Allowed = (char **)realloc(Allowed,
- X (a_alloced += 8) * sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X
- X if (fgets(tmp, 128, fp) == NULL)
- X break;
- X if ((len = strlen(tmp)) == 0)
- X break;
- X
- X tmp[--len] = '\0';
- X if (!len)
- X continue;
- X if ((Allowed[a_cnt] = malloc(1+len)) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(Allowed[a_cnt++], tmp);
- X }
- X if (a_cnt)
- X faxperms = ALLOWED;
- X fclose(fp);
- X }
- X else
- X {
- X sprintf(tmp, "%s/fax.deny", FAXLIB);
- X if ((fp = fopen(tmp, "r")) != NULL)
- X {
- X if ((Denied = (char **)malloc(8*sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X d_alloced = 8;
- X
- X for (;;)
- X {
- X if (d_cnt == d_alloced)
- X {
- X if ((Denied = (char **)realloc(Denied,
- X (d_alloced += 8) * sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X
- X if (fgets(tmp, 128, fp) == NULL)
- X break;
- X if ((len = strlen(tmp)) == 0)
- X break;
- X
- X tmp[--len] = '\0';
- X if (!len)
- X continue;
- X if ((Denied[d_cnt] = malloc(1+len)) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(Denied[d_cnt++], tmp);
- X }
- X if (d_cnt)
- X faxperms = DENIED;
- X else faxperms = ALL;
- X fclose(fp);
- X }
- X }
- X if (!faxperms)
- X faxperms = ROOT;
- X return(get_boss_perms());
- X}
- Xget_boss_perms()
- X{
- X FILE *fp;
- X int cn_alloced, len;
- X
- X cn_alloced = 0;
- X sprintf(tmp, "%s/fax.always", FAXLIB);
- X if ((fp = fopen(tmp, "r")) != NULL)
- X {
- X if ((CanNow = (char **)malloc(8*sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X cn_alloced = 8;
- X
- X for (;;)
- X {
- X if (cn_cnt == cn_alloced)
- X {
- X if ((CanNow = (char **)realloc(CanNow,
- X (cn_alloced += 8) * sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X
- X if (fgets(tmp, 128, fp) == NULL)
- X break;
- X if ((len = strlen(tmp)) == 0)
- X break;
- X tmp[--len] = '\0';
- X if (!len)
- X continue;
- X if ((CanNow[cn_cnt] = malloc(1+len)) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(CanNow[cn_cnt++], tmp);
- X }
- X fclose(fp);
- X }
- X fax_log(3, "sendfax: faxperms %d, allowed %d, denied %d, always %d\n",
- X faxperms, a_cnt, d_cnt, cn_cnt);
- X return(0);
- X}
- Xread_job(fp, xn)
- XFILE *fp;
- Xchar *xn;
- X{
- X int i;
- X
- X if (fax.phone_nos) /* has been called before, clean up */
- X {
- X for (i=0; i<fax.phone_nos; i++)
- X if (fax.phone[i] != NULL)
- X free(fax.phone[i]);
- X free(fax.phone);
- X fax.phone = NULL;
- X fax.phone_nos = 0;
- X }
- X
- X/*
- X these are read in the order they're written
- X by the spooler, not they way the structure is designed
- X*/
- X if (getint(fp,&fax.spooled)) /* spool timestamp */
- X return(ERROR);
- X fax.tpos = ftell(fp); /* might need to rewrite no of attempts */
- X if (getint(fp,&fax.tries)
- X || getstring(fp,fax.user) || getint(fp,&fax.uid)
- X || getint(fp,&fax.now) || getint(fp,&fax.mail)
- X || getint(fp,&fax.type)
- X || getint(fp,&fax.hires)
- X || getstring(fp,tmp) /* font, don't need to know this */
- X || getstring(fp,tmp)) /* retfax, don't need to know either */
- X return(ERROR);
- X fax.ppos = ftell(fp); /* if we succeed on partial phone list */
- X if ((fax.phone_nos = getphone(fp)) <= 0) /* rewrite those not yet done */
- X return(ERROR);
- X if (getstring(fp,fax.dname))
- X return(ERROR);
- X strcpy(fax.xname, xn);
- X if (getint(fp,&fax.pages))
- X return(ERROR);
- X#ifdef JOBID
- X if (getstring(fp,fax.jobid))
- X return(ERROR);
- X#endif
- X return(0);
- X}
- Xgetstring(fp,s)
- XFILE *fp;
- Xchar *s;
- X{
- X char buf[80];
- X
- X if (fgets(io, 80, fp) == NULL)
- X return(ERROR);
- X if (sscanf(io, "%s %s",buf,s) != 2)
- X return(ERROR);
- X return(0);
- X}
- Xgetint(fp,n)
- XFILE *fp;
- Xint *n;
- X{
- X long l;
- X
- X if (fgets(io, 80, fp) == NULL)
- X return(ERROR);
- X if (sscanf(io, "%s %ld",tmp,&l) != 2)
- X return(ERROR);
- X *n = l;
- X return(0);
- X}
- Xgetphone(fp)
- XFILE *fp;
- X{
- X int i, p_entries=0, p_alloced=0;
- X char phone[80];
- X long oldpos;
- X
- X if ((fax.phone = (char **)malloc(8*sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X p_alloced = 8;
- X p_entries = 0;
- X
- X for (;;)
- X {
- X oldpos = ftell(fp);
- X
- X if (p_entries == p_alloced)
- X {
- X if ((fax.phone = (char **)realloc(fax.phone,
- X (p_alloced += 8) * sizeof(char *))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X }
- X
- X if (fgets(io, 80, fp) == NULL)
- X return(ERROR);
- X if (io[0] == '#')
- X continue;
- X if (!strncmp(io, "data", 4))
- X {
- X fseek(fp, oldpos, 0);
- X break;
- X }
- X if (sscanf(io, "%s %s",tmp,phone) < 2)
- X return(ERROR);
- X
- X if ((fax.phone[p_entries] = malloc(1+strlen(phone))) == NULL)
- X return(fax_log(ERROR,"sendfax: can't allocate memory\n"));
- X strcpy(fax.phone[p_entries++], phone);
- X }
- X for (i=p_entries; i<p_alloced; i++)
- X fax.phone[i] = NULL;
- X return(p_entries);
- X}
- Xchk_perms()
- X{
- X int i;
- X
- X if (faxperms == ALL)
- X return(FALSE);
- X else if ((faxperms == ROOT) && (!fax.uid))
- X return(FALSE);
- X else if (faxperms == ALLOWED)
- X {
- X for (i=0; i<a_cnt; i++)
- X if (!strcmp(fax.user, Allowed[i]))
- X return(FALSE);
- X }
- X else if (faxperms == DENIED)
- X {
- X for (i=0; i<d_cnt; i++)
- X if (!strcmp(fax.user, Denied[i]))
- X return(ERROR);
- X return(FALSE);
- X }
- X return(ERROR);
- X}
- Xnot_now(uid,now,phone)
- Xint uid, now;
- Xchar *phone;
- X{
- X int i;
- X time_t cur;
- X struct tm *tml, *localtime();
- X
- X if (fax.now)
- X {
- X if (!fax.uid) /* if root can edit fax.config it can fax now */
- X return(FALSE);
- X for (i=0; i<cn_cnt; i++)
- X if (!strcmp(fax.user, CanNow[i]))
- X return(FALSE);
- X }
- X
- X for (i=0; i<h_entries; i++) /* check area/cty codes for restrictions */
- X if (match(phone, hour_ptr[i].dialcode))
- X {
- X (void)time(&cur);
- X tml = localtime(&cur); /* if not allowed at this hour */
- X if (!hour_ptr[i].hours[tml->tm_hour])
- X return(ERROR);
- X return(FALSE);
- X }
- X return(FALSE); /* no restrictions on this phone number */
- X}
- Xrmjob(xname,dname,pages)
- Xchar *xname,*dname;
- Xint pages;
- X{
- X char buf[256], *d;
- X int i;
- X
- X unlink(xname);
- X for (i=0; i<pages; i++)
- X {
- X sprintf(buf,"%s.g3.%d",dname,i);
- X unlink(buf);
- X }
- X}
- END_OF_FILE
- if test 20157 -ne `wc -c <'faxhost/sendfax.c'`; then
- echo shar: \"'faxhost/sendfax.c'\" unpacked with wrong size!
- fi
- # end of 'faxhost/sendfax.c'
- fi
- echo shar: End of archive 2 \(of 5\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-